﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using PlayingCardLib;

namespace Concentration
{
    public partial class MainForm : Form
    {
        const int NUM_CARDS = 32;
        const int NUM_COLS = 8;
        const int CARD_WIDTH = 75;
        const int CARD_HEIGHT = 107;
        const int GAP_X = 20;
        const int GAP_Y = 20;
        const int REWARD_SCORE = 100;
        const int MISSING_SCORE = 20;

        Deck deck;
        PictureBox[] cards;

        private Image back;
        private List<Image> faces = new List<Image>();

        private List<PictureBox> clickedCards = new List<PictureBox>();
        private int score = 0;
        private string highestScorePlayer = "Default";
        private int highestScore = 0;
        private int faceDownCardsNum = NUM_CARDS;

        bool frozen = false;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            // set the timer
            timer1.Interval = 2000;
            // read scores from a file
            ReadData();

            // init score and highest score
            labelScore.Text = string.Format("Score: {0}", score);
            labelHighestScore.Text = string.Format("Highest Score: {0} by {1}", highestScore, highestScorePlayer);
            /*
            PictureBox myPicturebox = new PictureBox();
            myPicturebox.Width = 100;
            myPicturebox.Height = 300;
            myPicturebox.Location = new Point(200, 150);
            this.Controls.Add(myPicturebox);
            */

            deck = new Deck(CardRank.Seven, CardRank.Eight, CardRank.Nine, CardRank.Ten, CardRank.Jack, CardRank.Queen, CardRank.King, CardRank.Ace);
            // deck = new Deck(CardRank.Seven, CardRank.Eight);
            for (int i = 0; i <= 51; i++)
            {
                faces.Add(cardImages.Images[i]);
            }
            back = cardImages.Images[56];
            deck.AssignImages(faces, back);
            deck.Shuffle();

            cards = new PictureBox[NUM_CARDS];
            for(int i=0; i<cards.Count(); i++)
            {
                cards[i] = new PictureBox();
                PlayingCard card = deck.DealTopCard();
                card.IsFaceUp = false;
                cards[i].Image = card.GetImage();
                cards[i].Width = CARD_WIDTH;
                cards[i].Height = CARD_HEIGHT;
                cards[i].Tag = card;
                cards[i].Click += Card_Click;
                int col = i % NUM_COLS;
                int row = i / NUM_COLS;
                cards[i].Location = new Point(col * ( GAP_X + CARD_WIDTH) + 20, row * (GAP_Y + CARD_HEIGHT) + 40);
                this.Controls.Add(cards[i]);
            }
            
        }  // MainForm_Load

        // Reset the game
        private void ResetGame()
        {
            buttonNewGame.Visible = false;
            score = 0;
            deck = new Deck(CardRank.Seven, CardRank.Eight, CardRank.Nine, CardRank.Ten, CardRank.Jack, CardRank.Queen, CardRank.King, CardRank.Ace);
            // deck = new Deck(CardRank.Seven, CardRank.Eight);
            back = cardImages.Images[56];
            deck.AssignImages(faces, back);
            deck.Shuffle();
            faceDownCardsNum = NUM_CARDS;
            clickedCards.Clear();
            for(int i=0; i<cards.Count(); i++)
            {
                cards[i].Visible = true;
                PlayingCard card = deck.DealTopCard();
                cards[i].Tag = card;
                cards[i].Image = card.GetImage();
            }
        } // reset game

        private void Card_Click(object sender, EventArgs e)
        {
            if (frozen) return;
            PictureBox pictureBox = (PictureBox)sender;  // will crush when ...
            // PictureBox pictureBox = sender as PictureBox // will get null when it is not a picture box;
            PlayingCard card = (PlayingCard)pictureBox.Tag;
            if (card.IsFaceUp) return; // avoid to click the face up cards
            card.Flip();
            pictureBox.Image = card.GetImage();
            pictureBox.Refresh();
            // 1. add the picture box to the list
            // 2. if there are two picture boxes in the list, check the ranks
            // 3. clear the list

            clickedCards.Add(pictureBox);
            if(clickedCards.Count == 2)
            {
                // cannot see the second card, need sleeping seconds
                frozen = true;
                timer1.Start();
                
                
            }
            
        }  // Card Click


        // Check ther result
        private void CheckResult()
        {
            timer1.Stop();

            PlayingCard cardOne = (PlayingCard)clickedCards[0].Tag;
            PlayingCard cardTwo = (PlayingCard)clickedCards[1].Tag;

            if(cardOne.Rank == cardTwo.Rank)
            {
                clickedCards[0].Visible = false;
                clickedCards[1].Visible = false;
                faceDownCardsNum -= 2;
                // Add score
                score += REWARD_SCORE;

                if (faceDownCardsNum == 0) CheckScores();
            }
            else
            {
                score -= MISSING_SCORE;
                cardOne.Flip();
                clickedCards[0].Image = cardOne.GetImage();
                cardTwo.Flip();
                clickedCards[1].Image = cardTwo.GetImage();
            }

            clickedCards.Clear();

            // refresh score
            labelScore.Text = string.Format("Score: {0}", score);
            frozen = false;
        }

        // check the scores, when the game is finished
        private void CheckScores()
        {
            if(score > highestScore)
            {
                highestScore = score;
                
                textBoxName.Visible = true;
                buttonSubmitName.Visible = true;
            }
            else
            {
                buttonNewGame.Visible = true;
            }
        } // CheckScores

        private void buttonSubmitName_Click(object sender, EventArgs e)
        {
            highestScorePlayer = textBoxName.Text;
            labelHighestScore.Text = string.Format("Highest Score: {0} by {1}", highestScore, highestScorePlayer);
            WriteData();
            textBoxName.Visible = false;
            buttonSubmitName.Visible = false;
            buttonNewGame.Visible = true;
        } // Submit Name Button


        // Read the highest score from highestScore.txt
        // format:
        // player:score
        private void ReadData()
        {
            using (StreamReader sr = new StreamReader(@"./highestScore.txt"))
            {
                string line = sr.ReadLine().Trim();
                string[] items = line.Split(':');
                highestScorePlayer = items[0];
                highestScore = int.Parse(items[1]);
            }
        }

        private void WriteData()
        {
            using (StreamWriter sw = new StreamWriter(@"./highestScore.txt"))
            {
                string result = string.Format("{0}:{1}", highestScorePlayer, highestScore);
                sw.WriteLine(result);
            }
        }

        private void buttonNewGame_Click(object sender, EventArgs e)
        {
            ResetGame();
        } // Reset Game Button

        private void timer1_Tick(object sender, EventArgs e)
        {
            CheckResult();
        }
    }
}
